package com.wcs.exam.common.util;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.apache.hc.client5.http.ClientProtocolException;
import org.apache.hc.client5.http.config.ConnectionConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.support.ClassicRequestBuilder;
import org.apache.hc.core5.http.message.BasicNameValuePair;
import org.apache.hc.core5.http.message.StatusLine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * http调用工具类
 *
 * @author wcs
 */
public final class HttpUtils {
    private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class);

    private static final String CHARSET_UTF_8 = "UTF-8";
    private static final int TIMEOUT = 10000;

    private HttpUtils() {
    }

    public static JSONObject postForObject(String url, Map<String, Object> map) {
        String result = HttpUtil.post(url, JSONUtil.toJsonStr(map), TIMEOUT);
        logger.info("POST 请求，url={}，map={}, result{}", url, map.toString(), result);
        return JSONUtil.parseObj(result);
    }

    public static <T> T getForObject(String url, Map<String, Object> map, Class<T> clazz) {
        logger.info("GET 请求， url={}，map={}", url, map.toString());
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
        }
        return getRestTemplate().getForObject(url + "?" + sb, clazz);
    }

    /**
     * @param url   请求地址
     * @param param 请求参数
     * @return 响应信息
     */
    public static String post(String url, Map<String, Object> param) {
        logger.info("POST 请求， url={}，map={}", url, param.toString());
        try {
            // 创建请求对象
            CloseableHttpClient client = HttpClients.custom()
                    .setConnectionManager(PoolingHttpClientConnectionManagerBuilder.create()
                            .setDefaultConnectionConfig(ConnectionConfig.custom()
                                    .setConnectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
                                    .setSocketTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
                                    .build()
                            )
                            .build()
                    )
                    .setDefaultRequestConfig(RequestConfig.custom()
                            .setConnectionRequestTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
                            .build()
                    )
                    .build();

            // 处理参数
            List<BasicNameValuePair> naps = param.entrySet().stream()
                    .filter(entry -> entry.getValue() != null)
                    .map(entry -> new BasicNameValuePair(entry.getKey(), entry.getValue().toString()))
                    .toList();

            // 处理请求
            ClassicHttpRequest httpPost = ClassicRequestBuilder
                    .post(url.trim())
                    .setEntity(new UrlEncodedFormEntity(naps, StandardCharsets.UTF_8))
                    .build();

            // 请求执行
            return client.execute(httpPost, response -> {
                if (response.getCode() >= 300) {
                    throw new ClientProtocolException(new StatusLine(response).toString());
                }
                final HttpEntity responseEntity = response.getEntity();
                if (responseEntity == null) {
                    return null;
                }
                return EntityUtils.toString(responseEntity, CHARSET_UTF_8);
            });

        } catch (Exception e) {
            logger.info("HTTP请求出错", e);
        }
        return "";
    }

    private static RestTemplate getRestTemplate() {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(TIMEOUT);
        factory.setReadTimeout(TIMEOUT);
        return new RestTemplate(factory);
    }
}
